﻿using System;
using System.Collections.Generic;
using System.Diagnostics;

using ExtensibleEventViewer.Core.Primitives;

using log4net;


namespace ExtensibleEventViewer.Providers
{
	internal static class Extensions
	{
		private readonly static ILog _log = LogManager.GetLogger(typeof(Extensions));

		internal static EventLogEntity[] ConvertToEventLogEntityArray(this EventLog[] eventLogs)
		{
			List<EventLogEntity> result = new List<EventLogEntity>(eventLogs.Length);

			for (int i = 0; i < eventLogs.Length; i++)
			{
				try
				{
					result.Add(eventLogs[i].ConvertToEventLogEntity());
				}
				catch (Exception ex)
				{
					_log.Error(ex.Message, ex);
				}
			}

			return result.ToArray();
		}

		internal static EventLogRecord[] ConvertToEventLogRecordArray(this EventLogEntryCollection eventLogEntries)
		{
			EventLogRecord[] result = new EventLogRecord[eventLogEntries.Count];

			for (int i = 0; i < eventLogEntries.Count; i++)
			{
				result[i] = eventLogEntries[i].ConvertToEventLogRecord();
			}

			return result;
		}

		internal static EventLogRecord ConvertToEventLogRecord(this EventLogEntry eventLogEntry)
		{
			return new EventLogRecord(
				eventLogEntry.InstanceId,
				eventLogEntry.MachineName,
				eventLogEntry.Source,
				eventLogEntry.TimeGenerated,
				eventLogEntry.Message,
				eventLogEntry.EntryType.ConvertToEventLogRecordType(),
				eventLogEntry.Category,
				eventLogEntry.UserName);
		}

		internal static EventLogRecordType ConvertToEventLogRecordType(this EventLogEntryType entryType)
		{
			switch (entryType)
			{
				case EventLogEntryType.Error:
					return EventLogRecordType.Error;
				case EventLogEntryType.Information:
					return EventLogRecordType.Information;
				case EventLogEntryType.Warning:
					return EventLogRecordType.Warning;
				default:
					return EventLogRecordType.Unknown;
			}
		}

		internal static EventLogEntity ConvertToEventLogEntity(this EventLog eventLog)
		{
			Func<IEnumerable<EventLogRecord>> exp = eventLog.Entries.ConvertToEventLogRecordArray;
			Func<bool> clearDelegate = eventLog.SafeClearRecords;

			EventLogEntity result = new EventLogEntity(
				eventLog.LogDisplayName,
				eventLog.MachineName,
				exp,
				clearDelegate);

			return result;
		}

		private static bool SafeClearRecords(this EventLog eventLog)
		{
			try
			{
				eventLog.Clear();

				return true;
			}
			catch (Exception ex)
			{
				return false;
			}
		}
	}
}
